package net.oschina.dajiangnan.wx.process.pay;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.oschina.dajiangnan.wx.util.ConstantConfig;
import net.oschina.dajiangnan.wx.util.HttpTookit;
import net.oschina.dajiangnan.wx.util.RandomUtil;
import net.oschina.dajiangnan.wx.util.Signature;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import net.oschina.dajiangnan.wx.constants.Config;
import net.oschina.dajiangnan.wx.constants.DynamicValue;
import net.oschina.dajiangnan.wx.constants.PathDefine;
import net.oschina.dajiangnan.wx.process.pay.bean.Product;
import net.oschina.dajiangnan.wx.process.pay.json.BuyInfo;
import net.oschina.dajiangnan.wx.process.pay.json.JsConfig;
import net.oschina.dajiangnan.wx.process.pay.json.WebAuthAccessToken;
import net.oschina.dajiangnan.wx.process.pay.tools.Unifiedorder;
import net.oschina.dajiangnan.wx.process.pay.tools.Unifiedorder.Result;
import net.oschina.dajiangnan.wx.process.pay.tools.Unifiedorder.UnifiedorderRespUnlegalSign;

public class H5_pay {

	private static Logger logger = Logger.getLogger(H5_pay.class);

	private static final String CONFIG_FILE_NAME = "wxpayconf/WXPayConf.properties";

	private static final String oauth2_url_prefix = "https://api.weixin.qq.com/sns/oauth2/access_token?";

	public String process(HttpServletRequest req, HttpServletResponse resp)
			throws UnsupportedEncodingException {

		if (!StringUtils.isEmpty(req.getParameter("state"))
				&& req.getParameter("state").equals(
						PathDefine.H5_PAY_PATH_STATE)) {
			// 根据code获取openid
			if (!StringUtils.isEmpty(req.getParameter("code"))) {
				try {
					String backJson = new HttpTookit().doGet(
							oauth2_url_prefix + "appid=" + Config.appid
									+ "&secret=" + Config.appSecret + "&code="
									+ req.getParameter("code")
									+ "&grant_type=authorization_code", null,
							"UTF-8");
					WebAuthAccessToken webAuthAccessToken = JSON.toJavaObject(
							JSON.parseObject(backJson),
							WebAuthAccessToken.class);
					String openid = webAuthAccessToken.getOpenid();
					logger.debug("网页授权获取openid = " + openid);

					String buyInfo = getBuyInfo(req, openid);

					String pageUrl = req.getRequestURL().toString() + "?"
							+ req.getQueryString();
					String result = ConstantConfig
							.getContentValue("jscontent/h5pay.jscontent")
							.replaceAll("#buy_info#", buyInfo)
							.replaceAll("#config#", getJsConfigContent(pageUrl));

					// logger.debug("backContent = " + result);

					return result;

				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {
				// 用户拒绝
				// snsapi_base 用户无感知
			}
		} else {
			// 客户端访问微信地址获取code
			String callBackURL = req.getParameter("callBackURL");
			String productBody = req.getParameter("productBody");
			String productDetail = req.getParameter("productDetail");
			String productFee = req.getParameter("productFee");

			if (StringUtils.isEmpty(callBackURL)
					|| StringUtils.isEmpty(productBody)
					|| StringUtils.isEmpty(productDetail)
					|| StringUtils.isEmpty(productFee)) {
				return "params lack";
			}
			try {
				if (Integer.parseInt(productFee) < 1) {
					return "productFee unlegal";
				}
			} catch (java.lang.NumberFormatException e) {
				return "productFee unlegal";
			}

			String param = "?callBackURL="
					+ java.net.URLEncoder.encode(callBackURL, "UTF-8")
					+ "&productBody=" + productBody + "&productDetail="
					+ productDetail + "&productFee=" + productFee;

			// 获取redirect_uri
			String redirect_uri = "";
			Properties pro = new Properties();
			InputStream is = H5_pay.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME);
			try {
				pro.load(is);
				redirect_uri = (String) pro.get("redirect_uri") + param;
			} catch (Exception e) {
				logger.error("Do not load " + CONFIG_FILE_NAME, e);
				return "Do not load " + CONFIG_FILE_NAME;
			} finally {
				try {
					is.close();
					pro.clear();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			// String redirect_uri = req.getRequestURL().toString() + param;
			String encode_redirect_uri = java.net.URLEncoder.encode(
					redirect_uri, "UTF-8");

			return ConstantConfig
					.getContentValue("jscontent/authorize.jscontent")
					.replaceAll("#appid#", Config.appid)
					.replaceAll("#redirect_uri#", encode_redirect_uri)
					.replaceAll("#state#", PathDefine.H5_PAY_PATH_STATE);
		}
		return null;
	}

	private String getJsConfigContent(String url) {

		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("timestamp", System.currentTimeMillis() / 1000);
		map.put("noncestr", RandomUtil.getRandomNumber(32));
		map.put("jsapi_ticket", DynamicValue.getJsApiTicket());
		map.put("url", url);

		String signature = Signature.getJsSign(map);

		JsConfig jsConfig = new JsConfig();
		jsConfig.setAppId(Config.appid);
		jsConfig.setDebug(false);
		jsConfig.setJsApiList("['chooseWXPay']");
		jsConfig.setNonceStr(map.get("noncestr").toString());
		jsConfig.setSignature(signature);
		jsConfig.setTimestamp(((Long) map.get("timestamp")).intValue());

		return JSON.toJSONString(jsConfig);
	}

	private String getBuyInfo(HttpServletRequest req, String openid)
			throws UnifiedorderRespUnlegalSign {

		String callBackURL = req.getParameter("callBackURL");
		String productBody = req.getParameter("productBody");
		String productDetail = req.getParameter("productDetail");
		String productFee = req.getParameter("productFee");

		Product product = new Product();
		product.setProductid("0");// JSAPI的方式不需要productid,为统一“统一下单接口,固定传0”
		product.setBody(productBody);
		product.setDetail(productDetail);
		product.setFee(Integer.parseInt(productFee));

		Result result = Unifiedorder.get(req, openid, product,Unifiedorder.TradeType.JSAPI);
		HashMap<String, Object> paramsMap = new HashMap<String, Object>();
		paramsMap.put("appId", Config.appid);
		paramsMap.put("timeStamp", System.currentTimeMillis() / 1000);
		paramsMap.put("nonceStr", RandomUtil.getRandomStr(32));
		paramsMap.put("package", "prepay_id=" + result.getPrepayid());
		paramsMap.put("signType", "MD5");
		String sign = Signature.getSign(paramsMap, Config.apikey);

		BuyInfo buyInfo = new BuyInfo();
		buyInfo.setAppId(Config.appid);
		buyInfo.setTimestamp(((Long) paramsMap.get("timeStamp")).intValue());
		buyInfo.setNonceStr(paramsMap.get("nonceStr").toString());
		buyInfo.setPackage_(paramsMap.get("package").toString());
		buyInfo.setSignType("MD5");
		buyInfo.setPaySign(sign);

		if (callBackURL.indexOf("?") == -1) {
			callBackURL += "?";
		} else {
			callBackURL += "&";
		}
		buyInfo.setReturnURL(callBackURL);
		return JSON.toJSONString(buyInfo);
	}

	public static void main(String args[]) {
		// 获取redirect_uri
		String redirect_uri = "";
		Properties pro = new Properties();	
		InputStream is = H5_pay.class.getClassLoader().getResourceAsStream(CONFIG_FILE_NAME);
		try {
			pro.load(is);
			redirect_uri = (String) pro.get("redirect_uri");
			System.out.println(redirect_uri);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("Do not load " + CONFIG_FILE_NAME, e);
		} finally {
			try {
				is.close();
				pro.clear();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}